﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;


namespace Scheduler
{
    /**Class: NumPerHour
     * @author Sara Tuohy
     * @version 1.0
     * Course : ITEC 4860 Spring, 2012
     * Written: March, 2012
     */
    public partial class NumPerHour : Form
    {
        /**
         * list of open time slots */
        private String[] hoursList;
        /**
         * TextBoxes to set the number of employees needed for each slot    */
        private MaskedTextBox[] employeeCountsTextBoxes;
        /**
        * number of employees needed for each slot                          */
        private int[] numberOfEmployeesNeeded;
        /**
         * For DB we need all 24 hours -                                    */
        //private int[] fullDayRequirement;
        /**
         * the operationDay these data apply to                             */
        private OperationDay theDay;
        /**
         * set to true if valid data input and saved                        */
        private bool validatedQuantities;

        /**Method: NumPerHour constructor
         * Constructor
         * Instantiates the object
         * @param hrList String[] of time increments the business is open
         * @param opDay the OperationDay in question
         */
        public NumPerHour(String[] hrList, OperationDay opDay)
        {
            hoursList = hrList;
            theDay = opDay;
            validatedQuantities = false;
            InitializeComponent();

            //this should never, ever happen:
            if (hoursList == null)
            {
                MessageBox.Show("HoursList is null", "Error Cannot Continue",
                  MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            employeeCountsTextBoxes = new MaskedTextBox[hoursList.Length];
            numberOfEmployeesNeeded = theDay.getNumPerTimeSlot();
            formatTable();
        }

        /**Method: formatTable
         * Layout table for manager's input
         * Purpose: since we can't know (until the object is instantiated) how many time slots there will
         * be, the input table is generated dynamically to meet the runtime need.
         */
        private void formatTable()
        {

            if (hoursList == null)
            {
                MessageBox.Show("HoursList is null", "Error Cannot Continue",
                  MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            else
            {
                this.numPerHourTabLayoutPan.ColumnCount = 2;
                int colNum0 = 0;
                int colNum1 = 1;
                //If the business is open till 10PM (22:00) the last half hour increment that needs to be
                //staffed is the one that starts at 9:30 (21:30).  Thats why "-1" was added to the for
                //loop limiter ...
                for (int i = 0; i < hoursList.Length - 1; i++)
                {
                    this.numPerHourTabLayoutPan.GrowStyle = TableLayoutPanelGrowStyle.AddRows;
                    this.numPerHourTabLayoutPan.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F));
                    this.numPerHourTabLayoutPan.Controls.Add(defineTableLabel(hoursList[i]), colNum0, i);
                    employeeCountsTextBoxes[i] = defineTableMaskedTB(i);
                    this.numPerHourTabLayoutPan.Controls.Add(employeeCountsTextBoxes[i], colNum1, i);
                }
                //there were format inconsistencies until this unneeded label was added.
                numPerHourTabLayoutPan.Controls.Add(defineTableLabel(""), colNum0, hoursList.Length);
            }
        }

        /**Method: defineTableLabel
         * returns a label for use in the input table
         * Purpose: one method to generate labels means single code to debug or enhance
         * @param string txt the text to be shown on the label
         * @return the label
         */
        private Label defineTableLabel(String txt)
        {
            Label newLabel = new System.Windows.Forms.Label();
            newLabel.AutoSize = true;
            newLabel.Anchor = AnchorStyles.Right;
            newLabel.Font = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Regular, GraphicsUnit.Pixel);
            newLabel.Visible = true;
            newLabel.Location = new System.Drawing.Point(3, 0);
            newLabel.Size = new System.Drawing.Size(43, 13);
            newLabel.Text = txt;
            return newLabel;
        }

        /**Method: defineTableMaskedTB
         * Formats the text box, integer input only, 0 to 9999 per requirements
         * Purpose: all code for the MaskedTextBoxes in one place
         * @param int ctr is used to set the tab order
         * @return the MaskedTextBox for the table
         */
        private MaskedTextBox defineTableMaskedTB(int ctr)
        {
            MaskedTextBox mtb = new System.Windows.Forms.MaskedTextBox();
            mtb.Location = new System.Drawing.Point(701, 140);
            mtb.Size = new System.Drawing.Size(40, 20);
            mtb.BeepOnError = true;
            mtb.Mask = "9990";
            mtb.Text = numberOfEmployeesNeeded[ctr].ToString();
            mtb.Anchor = AnchorStyles.Left;
            mtb.RightToLeft = System.Windows.Forms.RightToLeft.No;
            mtb.TabIndex = ctr;
            return mtb;
        }

        /**Method: requirementsSet
         * Verifies to caller that numbers were saved
         * Purpose: to spare caller getting an empty array or null value
         * and to enable clear error if request cannot be honored
         * @return bool validatedQuantities true means numbers were saved
         */
        public bool requirementsSet()
        {
            return validatedQuantities;
        }

        /**Method: getEmployeeCounts
         * get numbers needed per time slot
         * Purpose: return the numbers collected
         * @return int[] number needed for each time slot
         */
        public int[] getEmployeeCounts()
        {
            return numberOfEmployeesNeeded;
        }

        /**Method: numPerHourSaveButton_Click
         * Saves input data
         * Purpose: validate input, set employee counts and validatedQuantities values
         */
        private void numPerHourSaveButton_Click(object sender, EventArgs e)
        {
            int[] empsNeeded = new int[hoursList.Length];
            string numNeededStr;
            int numNeeded;
            bool dataWasValid = true;

            for (int i = 0; i < hoursList.Length - 1; i++)
            {
                numNeededStr = employeeCountsTextBoxes[i].Text;
                if (Int32.TryParse(numNeededStr, out numNeeded))
                {
                    empsNeeded[i] = numNeeded;
                }       //end if an integer
                else
                {
                    String time = hoursList[i];
                    String errMsg = System.String.Format("Cannot save; value at time {0} is non-numeric.", time);
                    MessageBox.Show(errMsg, "Error!",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    dataWasValid = false;
                    break;
                }       //end of else was NOT an integer
            }           //end for i=0 to length loop
            if (dataWasValid)
            {
                saveTheData(empsNeeded);
            }           //end if valid data, update the number of employees needed per hour and save it.
        }               //end numPerHourSaveButton_Click

        /**Method: saveTheData
         * Saves the Staffing Requirements
         * Purpose: sets the OperationDay time requirements
         * @param int[] the employees needed for each time slot
         */
        private void saveTheData(int[] empsNeeded)
        {
            numberOfEmployeesNeeded = empsNeeded;
            validatedQuantities = true;
            //update the OperationDay information
            theDay.setNumPerTimeSlot(empsNeeded);
            //the following copies it to the all day format the DB needs
            theDay.copyToAllDayArray();
            //and now save it to the database ...
            Data_Access_Layer.StaffingRequirements staffReqData = new
                Data_Access_Layer.StaffingRequirements(theDay.getDayName(),
                    Scheduler.Presentation_Layer.GlobalVariables.GlobalCompanyID);
            if (staffReqData.locateStaffingRequirements())
            {
                Array dayAndData = formatArray(theDay.getNumPerAllTimeSlots());
                staffReqData.setAllPerHr(dayAndData);
                MessageBox.Show("Staff Required values saved for " + theDay.getDayName(), "Requirements Saved Successfully",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("Locate failed for staff requirements: " + theDay.getDayName(), "Save Failed",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /**Method: formatArray
         * Creates an object[] Array with the day name in the first position ([0])
         * and the number of employees needed for each time slot in positions 1-49
         * @param int[] staffNums input from user (# employees needed)
         * @return Array the object[] created
         */
        private Array formatArray(int[] staffNums)
        {
            object[] staffingRequirementsDayArray = new object[49];
            staffingRequirementsDayArray[0] = theDay.getDayName();
            for (int i = 0; i < staffNums.Length; i++)
            {
                //add 1 to i because the first entry in the object array is the day name
                staffingRequirementsDayArray[i + 1] = staffNums[i];
            }
            return staffingRequirementsDayArray;
        }

        /**Method: numPerHourCancelButton
         * Return to calling panel.
         */
        private void numPerHourCancelButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

    }                   //end numPerHour class
}
